(function(global) {

    var nodeArray = new Array();
    var conArray = new Array();
    var groupArray = new Array(); /** default group **/
    var colorArray = new Array();

    var glabel1 = ':'; /** global labels **/
    var glabel2 = ':';

    var layerType = {vertical: 0, horizontal: 1, circular: 2};

    var pipelinejs = {
        VERSION: '0.0.1',
        AUTHOR: 'peter.ducai@gmail.com'
    };

    if (global.pipelinejs) {
        throw new Error('pipelinejs has already been defined');
    } else {
        global.pipelinejs = pipelinejs;
    }

    pipelinejs.init = function() {
        pipelinejs.setGlobalLabels('NAME', 'IP');
        pipelinejs.setLayerType(layerType.horizontal);
        pipelinejs.addGroup('default', '#00C');
    };

    pipelinejs.setGlobalLabels = function(gl1, gl2) {
        glabel1 = gl1;
        glabel2 = gl2;
        console.log('labels set to 1: ' + glabel1 + ' and 2: ' + glabel2);
    };


    /**
     * Draws a rounded rectangle using the current state of the canvas. 
     * If you omit the last three params, it will draw a rectangle 
     * outline with a 5 pixel border radius 
     * @param {CanvasRenderingContext2D} ctx
     * @param {Number} x The top left x coordinate
     * @param {Number} y The top left y coordinate 
     * @param {Number} width The width of the rectangle 
     * @param {Number} height The height of the rectangle
     * @param {Number} radius The corner radius. Defaults to 5;
     * @param {Boolean} fill Whether to fill the rectangle. Defaults to false.
     * @param {Boolean} stroke Whether to stroke the rectangle. Defaults to true.
     */
    pipelinejs.roundRect = function(ctx, x, y, width, height, radius, fill, stroke) {
        ctx.beginPath();
        ctx.moveTo(x + radius, y);
        ctx.lineTo(x + width - radius, y);
        ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
        ctx.lineTo(x + width, y + height - radius);
        ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
        ctx.lineTo(x + radius, y + height);
        ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
        ctx.lineTo(x, y + radius);
        ctx.quadraticCurveTo(x, y, x + radius, y);
        ctx.closePath();
        ctx.stroke();
        ctx.fill();
    }

    pipelinejs.addNode = function(ctx, name, info, x, y, group) {

        if (group === undefined) {
            group = 'default';
            console.log('setting group to default for ' + name);
        } else {
            console.log('setting group to ' + group + ' for ' + info);
        }

        var newnode = {name: name, info: info, x: x, y: y, conns: 0};
        nodeArray.push(newnode);

        ctx.save();
        /** ctx.globalAlpha = 50 / 100; **/
        pipelinejs.roundRect(ctx, x - 2, y - 2, 104, 154, 5, 'blue', 'true');

        pipelinejs.roundRect(ctx, x, y, 100, 130, 5, 'black', 'true');

        ctx.fillStyle = pipelinejs.getGroupColor(group);
        ctx.fillRect(x, y + 40, 100, 85);



        //@FIX
        pipelinejs.roundRect(ctx, x, y + 130, 100, 20, 5, '#06F', 'true');

        ctx.fillStyle = "white";
        ctx.font = "11px Arial";
        ctx.fillText(glabel1 + ':' + name, x + 5, y + 15);
        ctx.fillText(glabel2 + ':' + info, x + 5, y + 30);
        ctx.restore();

        pipelinejs.roundRect(ctx, x, y + 130, 100, 20, 5, '#06F', 'true')

        console.log('node ' + newnode.name + ' added at ' + x + ':' + y);
    };

    pipelinejs.findIndexByKeyValue = function(obj, key, value)
    {
        var found = null;
        for (var i = 0; i < obj.length; i++) {
            if (obj[i][key] === value) {
                found = i;
            }
        }
        //console.log('find: ' + found);
        return found;
    };

    pipelinejs.addConnector = function(ctx, name, conname) {

        var offset = 50;
        var step = 15;
        var cid = name + '_' + conname;
        var i = this.findIndexByKeyValue(nodeArray, 'name', name);
        var newcon = {name: conname, conid: cid, x: nodeArray[i].x, y: nodeArray[i].y + offset + step * nodeArray[i].conns};
        conArray.push(newcon);
        

        if (nodeArray[i].conns < 5) {
            ctx.beginPath();
            ctx.fillStyle = "white";
            ctx.arc(nodeArray[i].x, nodeArray[i].y + offset + step * nodeArray[i].conns, 5, 0, Math.PI * 2, true);
            ctx.fill();

            ctx.fillStyle = "white";
            ctx.font = "10px Arial";
            ctx.fillText(conname, nodeArray[i].x + 10, nodeArray[i].y + offset + step * nodeArray[i].conns);
            ctx.closePath();
        } else {
//            ctx.beginPath();
//            ctx.fillStyle = "white";
//            ctx.arc(nodeArray[i].x+90, nodeArray[i].y + offset + step * nodeArray[i].conns, 5, 0, Math.PI * 2, true);
//            ctx.fill();
//
//            ctx.fillStyle = "white";
//            ctx.font = "10px Arial";
//            ctx.fillText(conname, nodeArray[i].x + 10, nodeArray[i].y + offset + step * nodeArray[i].conns);
//            ctx.closePath();
        }
    
        nodeArray[i].conns++;
        console.log('adding connector ' + cid + ':' + nodeArray[i].x + offset + '/' + nodeArray[i].y);
    };



    pipelinejs.addWire = function(ctx, name1, conid1, name2, conid2) {

        var a = this.findIndexByKeyValue(conArray, 'conid', name1 + '_' + conid1);
        var b = this.findIndexByKeyValue(conArray, 'conid', name2 + '_' + conid2);

        ctx.beginPath();
        ctx.fillStyle = "black";
        ctx.moveTo(conArray[a].x, conArray[a].y);
        ctx.lineTo(conArray[b].x, conArray[b].y);
        ctx.stroke();
        ctx.closePath();

        console.log('adding wire from ' + name1 + '_' + conid1 + ' to ' + name2 + '_' + conid2);
    };

    pipelinejs.setLayerType = function(layerType) {
        switch (layerType)
        {
            case 0:
                console.log('setting layout to VERTICAL');
                break;
            case 1:
                console.log('setting layout to HORIZONTAL');
                break;
            case 2:
                console.log('setting layout to CIRCULAR');
                break;
            default:
                console.log('NONE');
                break;
        }
    };

    pipelinejs.addGroup = function(groupname, groupcolor) {
        groupArray.push(groupname);
        colorArray.push(groupcolor);
        console.log('adding group ' + groupname);
    };

    pipelinejs.getGroupColor = function(groupname) {
        console.log('looking for ' + groupname + ' group');
        var ret = -1;
        for (var i in groupArray) {
            if (groupArray[i] === groupname) {
                ret = colorArray[i];
                console.log('found ' + colorArray[i] + ' color');
            }
        }
        return ret;
    };

    pipelinejs.consumeJSON = function(jsonfile) {

    };


})(typeof window === 'undefined' ? this : window);